﻿using FastEF.Util;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FastEF.Base
{
    public class BaseDbContext<T> : DbContext where T : TModel
    {
        private static string Base_ConnectionString = "Base_ConnectionString";
        public string TableName { set; get; }
        public string KeyFieldName { set; get; }
        public BaseDbContext()
            : base(Base_ConnectionString)
        {
            this.TableName = MapperUtil.GetTableName<T>();
            this.KeyFieldName = MapperUtil.GetKeyField<T>();
        }
        public BaseDbContext(string ConnectStringName)
            : base(ConnectStringName)
        {

        }
        public DbSet<T> Items  { get; set; }
        public List<T> FindList(string SQL)
        {
            var args = new DbParameter[] {};
            return this.Database.SqlQuery<T>(SQL, args).ToList<T>();
        }
        public List<T> FindListPage(string SQL, int PageNumber, int PageSize, string OrderBy)
        {
            var args = new DbParameter[] { };
            return this.Database.SqlQuery<T>(SQL, args).Skip(PageNumber).Take(PageSize).ToList<T>();
        }
        public T FindOne(string KeyGuid)
        {
            return FindOne(KeyFieldName, KeyGuid);
        }
        public T FindOne(string KeyName,string KeyGuid)
        {
            return this.Database.SqlQuery<T>(string.Format("select * from {0} where {1}='{2}'", TableName, KeyName, KeyGuid)).ToList().FirstOrDefault();
        }
        public void Insert(T Entity)
        {
            this.Set<T>().Add(Entity);
            this.SaveChanges();
        }
        public void InsertBatch(List<T> EntityList)
        {
            foreach (T item in EntityList)
            {
                this.Set<T>().Add(item);
            }
            this.SaveChanges();
        }
        public void Save(T Entity)
        {
            this.Entry<T>(Entity).State = EntityState.Modified;
            this.SaveChanges();
        }
        /// <summary>
        /// 更新指定列
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="SaveColumn"></param>
        public void Save<T>(T Entity, string[] SaveColumn) where T : TModel
        {
            foreach (var item in SaveColumn)
            {
                this.Entry(Entity).Property(item).IsModified = true;
            }
            this.SaveChanges();
        }
        /// <summary>
        /// 删除方法根据主键查找，空对象，给主键赋值，一样能够删除
        /// </summary>
        /// <param name="Entity"></param>
        public void Remove(T Entity)
        {
            this.Entry<T>(Entity).State = EntityState.Deleted;
            this.SaveChanges();
        }
        public int Count<T>()
        {
            return ExecuteSqlToInt(string.Format("select count(1) from {0}", TableName));
        }

        /// <summary>
        /// 联合查询返回，使用ado.net查询，仅针对mysql适配
        /// </summary>
        /// <param name="SQL"></param>
        /// <returns></returns>
        public List<JObject> FindView(string SQL)
        {
            List<JObject> list = new List<JObject>();
            MySqlConnection conn = new MySqlConnection();
            conn.ConnectionString = this.Database.Connection.ConnectionString;
            if (conn.State != ConnectionState.Open)
            {
                conn.Open();
            }
            MySqlCommand cmd = new MySqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = SQL;
            MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
            DataTable table = new DataTable();
            adapter.Fill(table);
            foreach (DataRow row in table.Rows)
            {
                JObject data = new JObject();
                foreach (DataColumn column in row.Table.Columns)
                {
                    data.Add(column.ColumnName, Convert.ToString(row[column.ColumnName]));
                }
                list.Add(data);
            }
            return list;
          
        }
        /// <summary>
        /// 联合分页查询返回，使用ado.net查询，仅针对mysql适配
        /// </summary>
        /// <param name="SQL"></param>
        /// <param name="PageNumber"></param>
        /// <param name="PageSize"></param>
        /// <returns></returns>
        public List<JObject> FindViewPage(string SQL, int PageNumber,int PageSize)
        {
            SQL += " limit " + (PageNumber - 1) * PageSize + "," + PageSize;
            var args = new DbParameter[] { };
            List<JObject> result = new List<JObject>();
            List<Object> data = this.Database.SqlQuery<Object>(SQL, args).Skip(PageNumber).Take(PageSize).ToList<Object>();
            foreach (var item in data)
            {
                result.Add(new JObject(item));
            }
            return result;
        }

        public void ExecuteSql(string SQL)
        {
            this.Database.ExecuteSqlCommand(SQL);
        }
        public int ExecuteSqlToInt(string SQL)
        {
            var args = new DbParameter[] { };
            return this.Database.SqlQuery<int>(SQL).ToList().FirstOrDefault();
        }
        public string ExecuteSqlToString(string SQL)
        {
            var args = new DbParameter[] { };
            return this.Database.SqlQuery<string>(SQL).ToList().FirstOrDefault();
        }
    }
}
